﻿
#region Using Directives.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
using System.Xml.Linq;
using RWXMLEdit.Common;

#endregion

namespace RWXMLEdit.Client.Forms
{
    public partial class FormEditStandardValues : Form
    {
        #region Fields.

        private XDocument _xDoc;
        private readonly Dictionary<string, double[]> _savedValues = new Dictionary<string, double[]>(); 
        private string _originalXml = string.Empty;
        private string _newXml = string.Empty;
        private string _typeName = string.Empty;
        private readonly RwMatrix _matrix = new RwMatrix();

        #endregion

        #region Constructors.

        public FormEditStandardValues(XDocument xdoc)
        {
            _xDoc = xdoc;

            InitializeComponent();
        }

        #endregion

        #region Properties.

        public XDocument GetXDocument
        {
            get { return _xDoc; }
        }

        public string GetOriginalXml
        {
            get { return _originalXml; }
        }

        public string GetNewXml
        {
            get { return _newXml; }
        }

        #endregion

        #region Events.

        private void FormEditCoupleLoad(object sender, EventArgs e)
        {
            Init();
        }

        private void BtnUpdateClick(object sender, EventArgs e)
        {
            btnUpdate.Enabled = false;

            grbMain.Enabled = false;

            if (!string.IsNullOrEmpty(_typeName))
            {
                _savedValues[_typeName] = _matrix.GetMatrix(); //GetMatrix();
            }

            foreach (KeyValuePair<string, double[]> savedValue in _savedValues)
            {
                string[] formatedValues = Functions.FormatValues(savedValue.Value);

                SetValues(savedValue.Key, formatedValues);
            }
        }

        private void cboStandardValues_SelectedIndexChanged(object sender, EventArgs e)
        {
            var tmp = new double[16];

            if(!string.IsNullOrEmpty(_typeName))
            {
                _savedValues[_typeName] = _matrix.GetMatrix(); //GetMatrix();
            }

            if (cboStandardValues.Items.Count > 0)
            {
                _typeName = cboStandardValues.SelectedItem.ToString();

                if (_savedValues.ContainsKey(_typeName))
                {
                    _savedValues.TryGetValue(_typeName, out tmp);

                    _matrix.SetMatrix(tmp); //SetMatrix(tmp);
                }
                else
                {
                    GetValues(_typeName);

                    _savedValues.Add(_typeName, _matrix.GetMatrix());// GetMatrix());
                }

                ShowValues();

                grbMain.Text = string.Format("Edit {0}", cboStandardValues.SelectedItem);
            }
        }

        private void nudXValue_ValueChanged(object sender, EventArgs e)
        {
            _matrix.SetXTranslation((double)nudXValue.Value);
            lblShowValues.Text = Functions.BuildResultString(_matrix.GetMatrix());//GetMatrix());
        }

        private void nudXRotation_ValueChanged(object sender, EventArgs e)
        {
            _matrix.SetXRotation((double)nudXRotation.Value);
            lblShowValues.Text = Functions.BuildResultString(_matrix.GetMatrix());//GetMatrix());
        }

        private void nudYValue_ValueChanged(object sender, EventArgs e)
        {
            _matrix.SetYTranslation((double)nudYValue.Value);
            lblShowValues.Text = Functions.BuildResultString(_matrix.GetMatrix());//GetMatrix());
        }

        private void nudYRotation_ValueChanged(object sender, EventArgs e)
        {
            _matrix.SetYRotation((double)nudYRotation.Value);
            lblShowValues.Text = Functions.BuildResultString(_matrix.GetMatrix());//GetMatrix());
        }

        private void nudZValue_ValueChanged(object sender, EventArgs e)
        {
            _matrix.SetZTranslation((double)nudZValue.Value);
            lblShowValues.Text = Functions.BuildResultString(_matrix.GetMatrix());//GetMatrix());
        }

        private void nudZRotation_ValueChanged(object sender, EventArgs e)
        {
            _matrix.SetZRotation((double)nudZRotation.Value);
            lblShowValues.Text = Functions.BuildResultString(_matrix.GetMatrix());//GetMatrix());
        }

        //private void nudXValue_Click(object sender, EventArgs e)
        //{
        //    if (!btnUpdate.Enabled)
        //        btnUpdate.Enabled = true;
        //}

        //private void nudXRotation_Click(object sender, EventArgs e)
        //{
        //    if (!btnUpdate.Enabled)
        //        btnUpdate.Enabled = true;
        //}

        //private void nudYValue_Click(object sender, EventArgs e)
        //{
        //    if (!btnUpdate.Enabled)
        //        btnUpdate.Enabled = true;
        //}

        //private void nudYRotation_Click(object sender, EventArgs e)
        //{
        //    if (!btnUpdate.Enabled)
        //        btnUpdate.Enabled = true;
        //}

        //private void nudZValue_Click(object sender, EventArgs e)
        //{
        //    if (!btnUpdate.Enabled)
        //        btnUpdate.Enabled = true;
        //}

        //private void nudZRotation_Click(object sender, EventArgs e)
        //{
        //    if (!btnUpdate.Enabled)
        //        btnUpdate.Enabled = true;
        //}

        #endregion

        #region Private Methods.

        private void Init()
        {
            Text = @"Edit Standard Attributes";

            StandardAttributes sa = StandardAttributes.FrontCouplingPivot;

            string[] tmp = sa.GetType().GetEnumNames();

            cboStandardValues.Items.AddRange(tmp);

            if(cboStandardValues.Items.Count > 0)
            {
                cboStandardValues.SelectedIndex = 0;
            }
        }

        //private void SetMatrix(double[] values)
        //{
        //    int counter = 0;

        //    for(int i = 0; i < 4; i++)
        //    {
        //        for(int j = 0; j < 4; j++)
        //        {
        //            _matrix.SetElement(i, j, values[counter]);
        //            counter++;
        //        }
        //    }

        //    _matrix.CalculateRotationAngles();
        //}

        //private double[] GetMatrix()
        //{
        //    double[] values = new double[16];
        //    int counter = 0;

        //    for (int i = 0; i < 4; i++)
        //    {
        //        for (int j = 0; j < 4; j++)
        //        {
        //            values[counter] = _matrix.GetElement(i, j);
        //            counter++;
        //        }
        //    }

        //    return values;
        //}

        private void GetValues(string type)
        {
            double[] values = new double[16];

            XElement doc = XElement.Load(_xDoc.CreateReader());

            XElement element = (from x in doc.DescendantsAndSelf()
                                       where (string)x.Attribute("name") ==
                                       type
                                       select x).SingleOrDefault();

            if(element != null)
            {
                _originalXml = element.ToString();

                IEnumerable<XElement> list = element.Descendants("sFloat32").ToList();

                if(!list.Any())
                {
                    Functions.AddSFloat32Tags(ref element);

                    list = element.Descendants("sFloat32").ToList();

                    _xDoc = XDocument.Load(doc.CreateReader(), LoadOptions.PreserveWhitespace);
                }


                int i = 0;

                foreach (var xElement in list)
                {
                    if(xElement != null)
                    {
                        var xElement1 = xElement.Element("Element");
                        if (xElement1 != null)
                        {
                            var element1 = xElement1.Element("Value");
                            if (element1 != null)
                            {
                                values[i] = Convert.ToDouble(element1.Value, CultureInfo.InvariantCulture.NumberFormat);
                            }    
                        }
                    }

                    i++;
                }

                _matrix.SetMatrix(values); //SetMatrix(values);
            }
        }

        private void SetValues(string type, string[] values)   
        {
            XElement doc = XElement.Load(_xDoc.CreateReader());

            XElement element = (from x in doc.DescendantsAndSelf()
                                where (string)x.Attribute("name") ==
                                type
                                select x).SingleOrDefault();

            if (element != null)
            {
                IEnumerable<XElement> list = element.Descendants("sFloat32");

                int i = 0;

                foreach (var xElement in list)
                {
                    if (xElement != null)
                    {
                        var xElement1 = xElement.Element("Element");
                        if (xElement1 != null)
                        {
                            var element1 = xElement1.Element("Value");
                            if (element1 != null)
                            {
                                element1.Value = values[i];
                            }
                        }
                    }

                    i++;
                }

                _newXml = element.ToString();

                _xDoc = XDocument.Load(doc.CreateReader(), LoadOptions.PreserveWhitespace);
            }
        }

        private void ShowValues()
        {
            double xValue = Functions.CheckValue(_matrix.GetXTranslation(), -999, 999);
            double yValue = Functions.CheckValue(_matrix.GetYTranslation(), -999, 999);
            double zValue = Functions.CheckValue(_matrix.GetZTranslation(), -999, 999);

            nudXValue.Value = (decimal)xValue;
            nudXRotation.Value = (decimal)_matrix.GetXRotation();

            nudYValue.Value = (decimal)yValue;
            nudYRotation.Value = (decimal)_matrix.GetYRotation();

            nudZValue.Value = (decimal)zValue;
            nudZRotation.Value = (decimal)_matrix.GetZRotation();

            lblShowValues.Text = Functions.BuildResultString(_matrix.GetMatrix());//GetMatrix());
        }
        
        #endregion

    }
}
